package com.hksj.Intelligentmanagement.mqtt.listener;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.hksj.Intelligentmanagement.dto.ObtainOrderDTO;
import com.hksj.Intelligentmanagement.dto.ObtainOrderResultDTO;
import com.hksj.Intelligentmanagement.entity.CallTaskOrderEntity;
import com.hksj.Intelligentmanagement.entity.CallUserEntity;
import com.hksj.Intelligentmanagement.mqtt.constant.Constant;
import com.hksj.Intelligentmanagement.mqtt.constant.TopicConstant;
import com.hksj.Intelligentmanagement.service.CallTaskOrderService;
import com.hksj.Intelligentmanagement.service.CallUserService;
import com.hksj.Intelligentmanagement.utils.RedisCache;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.redisson.Redisson;
import org.redisson.api.RLock;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.ObjectUtils;

import java.util.Date;
import java.util.concurrent.TimeUnit;

public class ObtainOrderListener extends ListenerMqttClientSupport implements MqttListener{
    @Autowired
    private Redisson redisson;

    @Autowired
    private CallTaskOrderService taskOrderService;

    @Autowired
    private CallUserService userService;

    @Autowired
    private RedisCache<String> strCache;

    @Override
    public void receive(String topic, MqttMessage mqttMessage) {
        ObtainOrderDTO obtainOrderDTO = JSONObject.parseObject(new String(mqttMessage.getPayload()), ObtainOrderDTO.class);
        if (!ObjectUtils.isEmpty(obtainOrderDTO)){
            getMqttClient().getCallBackAdapter().getExecutor().execute(() -> {
                //一次校验任务单是否存在
                String flag = strCache.getCacheObject(Constant.TO_OBTAIN_ORDER + obtainOrderDTO.getOrderNo());
                if (StrUtil.isNotBlank(flag)){
                    //任务单存在就开始抢单
                    RLock rLock = redisson.getLock(Constant.LOCK_OBTAIN_ORDER + obtainOrderDTO.getOrderNo());;
                    try{
                        //加锁
                        if (rLock.tryLock(10,10, TimeUnit.SECONDS)){
                            //二次校验
                            flag = strCache.getCacheObject(Constant.TO_OBTAIN_ORDER + obtainOrderDTO.getOrderNo());

                            if (StrUtil.isNotBlank(flag)){
                                //更新订单信息
                                CallTaskOrderEntity taskOrder = new CallTaskOrderEntity();
                                Date now = new Date();
                                taskOrder.setObtainAt(now);
                                taskOrder.setUpdateAt(now);
                                taskOrder.setState(CallTaskOrderEntity.STATUS_OBTAINED);
                                taskOrder.setObtainDeviceCode(obtainOrderDTO.getDeviceCode());

                                taskOrder.setObtainUserDevicePassword(obtainOrderDTO.getUserDevicePassword());
                                CallUserEntity user = userService.getUserByDevicePassword(obtainOrderDTO.getUserDevicePassword());
                                if (!ObjectUtils.isEmpty(user)){
                                    taskOrder.setObtainUserId(user.getId());
                                    taskOrder.setObtainUsername(user.getName());
                                }
                                LambdaQueryWrapper<CallTaskOrderEntity> query = new QueryWrapper<CallTaskOrderEntity>().lambda();
                                query.eq(CallTaskOrderEntity::getOrderNo,obtainOrderDTO.getOrderNo());
                                taskOrderService.update(taskOrder,query);

                                //发送通知
                                ObtainOrderResultDTO result = new ObtainOrderResultDTO(obtainOrderDTO.getOrderNo(), obtainOrderDTO.getDeviceCode(), now);
                                getMqttClient().publish(JSONObject.toJSONString(result),TopicConstant.obtain_order_result);

                                //获取成功
                                strCache.deleteObject(Constant.TO_OBTAIN_ORDER + obtainOrderDTO.getOrderNo());
                            }else{
                                //发送通知
                                obtainFail(obtainOrderDTO);
                            }
                        }
                    }catch (Exception e){
                        e.printStackTrace();
                    }finally {
                        rLock.unlock();
                    }
                }else {
                    //发送通知
                    obtainFail(obtainOrderDTO);
                }
            });
        }
    }

    private void obtainFail(ObtainOrderDTO obtainOrderDTO){
        //发送通知
        ObtainOrderResultDTO result = new ObtainOrderResultDTO(obtainOrderDTO.getOrderNo(), obtainOrderDTO.getDeviceCode(),new Date(),ObtainOrderResultDTO.FAIL);
        getMqttClient().publish(JSONObject.toJSONString(result),TopicConstant.obtain_order_result);
    }
}